<template>
    <div id="map">
        <div id="container">
            <p>位置精度: <code id="accuracy">{{position}}</code></p>
            <p>海拔高度: <code id="altitude">{{altitude}}</code></p>
            <p>海拔精度: <code id="altitudeAccuracy">{{altitudeAccuracy}}</code></p>
            <p>航向: <code id="heading">{{heading}}</code></p>
            <p>速度: <code id="speed">{{speed}}</code></p>
        </div>
    </div>
</template>

<script>
    import {Map, View, Geolocation, Feature} from 'ol'
    import {OSM, Vector as VectorSource} from 'ol/source';
    import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
    import {Point} from 'ol/geom'
    import {Style, Stroke, Circle, Fill} from 'ol/style'

    export default {
        name: "GeoLocation",
        data() {
            return {
                position: "",
                altitude: "",
                altitudeAccuracy: "",
                heading: "",
                speed: "",
            }
        },
        mounted() {
            //初始化地图
            this.map = new Map({
                target: 'map',//指定挂载dom，注意必须是id
                layers: [
                    new TileLayer({
                        source: new OSM()//加载OpenStreetMap
                    }),
                ],
                //配置视图
                view: new View({
                    center: [113.24981689453125, 23.126468438108688], //视图中心位置
                    projection: "EPSG:4326", //指定投影
                    zoom: 12   //缩放到的级别
                })
            });
            //创建一个定位控件
            var geolocation = new Geolocation({
                projection: this.map.getView().getProjection(), //设置投影参考系
                //追踪参数
                trackingOptions: {
                    maximumAge: 10000, //最大缓存时间
                    enableHighAccuracy: true, //启用高精度
                    timeout: 600000  // 超时时长
                }
            });

            // 添加定位控件的位置变更事件（更新面板的导航位置信息）
            geolocation.on('change', () => {
                this.position = geolocation.getAccuracy() + ' [m]';
                this.altitude = geolocation.getAltitude() + ' [m]';
                this.altitudeAccuracy = geolocation.getAltitudeAccuracy() + ' [m]';
                this.heading = geolocation.getHeading() + ' [rad]';
                this.speed = geolocation.getSpeed() + ' [m/s]';
            });

            let vectorSource = new VectorSource();
            //创建定位点矢量图层（featuresOverlay）
            var featuresOverlay = new VectorLayer({
                source: vectorSource
            });
            this.map.addLayer(featuresOverlay); //添加定位点标注（矢量要素图层）
            // 定位错误事件处理
            geolocation.on('error', (error) => {
                this.$message.error(error.message)
            });
            //精确模式定位点要素（一定分辨率下显示）
            var accuracyFeature = new Feature();
            geolocation.on('change:accuracyGeometry', function () {
                accuracyFeature.setGeometry(geolocation.getAccuracyGeometry());
            });
            //定位点要素
            var positionFeature = new Feature();
            positionFeature.setStyle(new Style({
                image: new Circle({
                    radius: 6,
                    fill: new Fill({
                        color: '#3399CC'
                    }),
                    stroke: new Stroke({
                        color: '#fff',
                        width: 2
                    })
                })
            }));
            //放入实时数据要素，位置要素
            vectorSource.addFeatures([accuracyFeature, positionFeature])
            //添加定位控件的导航位置变更事件处理
            geolocation.on('change:position', function () {
                var coordinates = geolocation.getPosition();
                positionFeature.setGeometry(coordinates ? new Point(coordinates) : null);
                this.flyLocation(coordinates);//飞行动画模式定位到导航点位点
            });

        },
        methods: {
            flyLocation(center) {
                var duration = 4000;//动画的持续时间（以毫秒为单位）
                var zoom = this.map.getView().getZoom();
                var parts = 2;
                var called = false;

                //动画完成的回调函数
                function callback(complete) {
                    --parts;
                    if (called) {
                        return;
                    }
                    if (parts === 0 || !complete) {
                        called = true;
                    }
                }

                //第一个动画
                this.map.getView().animate({
                    center: center,
                    duration: duration
                }, callback);
                //第二个动画
                this.map.getView().animate({
                    zoom: zoom - 1,
                    duration: duration / 2
                }, {
                    zoom: zoom,
                    duration: duration / 2
                }, callback);
            }
        }
    }
</script>

<style scoped>
    #map {
        width: 100%;
        height: 100%;
    }

    #container {
        position: absolute;
        bottom: 20px;
        right: 20px;
        width: 14%;
        height: 20%;
        padding: 5px 10px;
        background-color: rgba(0, 0, 0, 0.5);
        font-size: 14px;
        border-radius: 2px;
        z-index: 999;
    }
    #container p {
        color: rgb(255, 255, 255);
        line-height: 30px;
    }
    #container code{
        color:rgb(240, 244, 45);
    }
</style>